package com.robot.common.aop;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.google.gson.Gson;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Enumeration;


/**
 * @Description:打印接口请求日志
 * @author:lyq
 * @Date:2021-01-13 9:58
 * execution：用于匹配方法执行的连接点；
 * within：用于匹配指定类型内的方法执行；
 * this：用于匹配当前AOP代理对象类型的执行方法；注意是AOP代理对象的类型匹配，这样就可能包括引入接口也类型匹配；
 * target：用于匹配当前目标对象类型的执行方法；注意是目标对象的类型匹配，这样就不包括引入接口也类型匹配；
 * args：用于匹配当前执行的方法传入的参数为指定类型的执行方法；
 * @within：用于匹配所以持有指定注解类型内的方法；
 * @target：用于匹配当前目标对象类型的执行方法，其中目标对象持有指定的注解；
 * @args：用于匹配当前执行的方法传入的参数持有指定注解的执行；
 * @annotation：用于匹配当前执行方法持有指定注解的方法；
 * bean：Spring AOP扩展的，AspectJ没有对于指示符，用于匹配特定名称的Bean对象的执行方法；
 * reference pointcut：表示引用其他命名切入点，只有@ApectJ风格支持，Schema风格不支持。
 */
@Component
@Aspect
@Log4j2
public class ApiRequestLogAspect {

    /**
     * 系统模块
     */
    @Pointcut("within(com.robot.system.controller.*)")
    public void systemController() {}

    @Before("systemController()")
    public void before(JoinPoint joinPoint){
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        Object args[] = joinPoint.getArgs();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        String method1 = request.getMethod();
        String methodName = method.getName();
        String str = StringUtils.join(args,",");
        log.info(method.getDeclaringClass().getName()+"."+methodName);
        System.out.println("-------------------------------------------------------------------------------------------------------------------------------------------------------");
        //if(str != null && !str.equals("")){
            System.out.println("请求参数：{"+str+"}");
        //}
        System.out.println("请求头信息："+
                "method："+method1);
        //获取所有请求头名称
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            //根据名称获取请求头的值
            String value = request.getHeader(name);
            System.out.println("            "+name+"："+value);
        }
        System.out.println("");
    }

    @AfterReturning(value = "systemController()",returning = "rvt")
    public void after(JoinPoint joinPoint,Object rvt){
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        log.info(method.getDeclaringClass().getName()+"."+method.getName()+"\n"+"返回数据："+"{"+new Gson().toJson(rvt)+"}");
    }
}
